/**
 * 
 */
package com.chainwintel.prjmgmt.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ExceptionMapping;
import org.apache.struts2.convention.annotation.ExceptionMappings;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.chainwintel.prjmgmt.model.MenuItem;
import com.chainwintel.prjmgmt.service.MenuCategoryMgr;
import com.chainwintel.prjmgmt.service.MenuItemMgr;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;

/**
 * @author dearshor
 *
 */
@Component
@Results({
	@Result(name = "menu-tree", location = "menuTree2.jsp"),
	@Result(name = "menu-tree-c", location = "menuTree_component.jsp"),
	@Result(name = "menu-category-form-field", location = "menuCategoryFormField.jsp"),
	@Result(name = "menu-form-field", location = "menuFormField.jsp"),
	@Result(name = "ERROR",location = "error.jsp")

})
@ExceptionMappings({
	@ExceptionMapping(exception = "com.chainwintel.prjmgmt.exception.FailedToAssignOperationsException" ,result = "ERROR"),
	@ExceptionMapping(exception = "java.lang.RuntimeException", result = "ERROR"),
	@ExceptionMapping(exception = "java.lang.Exception" ,result = "ERROR")
})
public class MenuTreeAction extends ActionSupport implements Preparable {

	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 5820887310863480455L;

	private List<MenuItem> rootNodes;

	//	private MenuCategory parentCategory;

	//	private MenuCategory category;

	private MenuItem parentMenu;

	private long parentMenuId;

	private MenuItem menu;

	private long menuId;

	private long[] selectedNodeIds;

	@Autowired
	private MenuCategoryMgr categoryMgr ;

	@Autowired
	private MenuItemMgr menuItemMgr;

	public void prepare() throws Exception {
		// TODO Auto-generated method stub
		setRootNodes(menuItemMgr.listRootMenus());
	}

	@Action("/menuTree")
	public String menuTree() {
		return "menu-tree";
	}

	@Action("/menuTree_c")
	public String menuTreeComponent() {
		return "menu-tree-c";
	}

	@Action("/menuCategoryFormField")
	public String menuCategoryFormField() {
		return "menu-category-form-field";
	}

	@Action("/menuFormField")
	public String menuFormField() {
		return "menu-form-field";
	}

	//	@Action("/menutree_category_edit")
	//	public String editCategory() {
	//		try {
	//			if (selectedNodeIds != null && selectedNodeIds.length > 0) {
	//				setParentCategory(categoryMgr.find(selectedNodeIds[0]));
	//			}
	//			categoryMgr.edit(getParentCategory(),getCategory());
	//			return "menu-tree";
	//		} catch (DataAccessException e) {
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//			throw new RuntimeException("Operation failed.",e);
	//		}
	//	}

	@Action("/menutree_menu_edit")
	public String editMenu() {


		try {
			if (getMenu().getId() <= 0) {
				setMenu(new MenuItem());
				getMenu().setParentMenu(getParentMenu());
			}
			MenuItem menu = menuItemMgr.find(getMenu().getId());
			BeanUtils.copyProperties(menu, getMenu());
			menuItemMgr.merge(menu);
			return "menu-tree";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		}
	}

	//	@Action("/menutree_category_del")
	//	public String deleteCategory() {
	//		try {
	//			categoryMgr.remove(getCategory());
	//			return "menu-tree";
	//		} catch (DataAccessException e) {
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//			throw new RuntimeException("Operation failed.",e);
	//		}
	//	}

	@Action(value = "/menutree_menu_del")
	public String deleteMenu() {
		try {
			menuItemMgr.remove(getMenu());
			return "menu-tree";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		}
	}

	//	@Action("/menutree_category_del")
	//	public String deleteCategory() {
	//		try {
	//			categoryMgr.remove(getCategory());
	//			return "menu-tree";
	//		} catch (DataAccessException e) {
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//			throw new RuntimeException("Operation failed.",e);
	//		}
	//	}

	/**
	 * @param rootNodes the rootNodes to set
	 */
	public void setRootNodes(List<MenuItem> rootNodes) {
		this.rootNodes = rootNodes;
	}

	/**
	 * @return the rootNodes
	 */
	public List<MenuItem> getRootNodes() {
		return rootNodes;
	}

	/**
	 * @param parentCategory the parentCategory to set
	 */
	//	public void setParentCategory(MenuCategory parentCategory) {
	//		this.parentCategory = parentCategory;
	//	}

	/**
	 * @return the parentCategory
	 */
	//	public MenuCategory getParentCategory() {
	//		return parentCategory;
	//	}

	/**
	 * @param category the category to set
	 */
	//	public void setCategory(MenuCategory category) {
	//		this.category = category;
	//	}

	/**
	 * @return the category
	 */
	//	public MenuCategory getCategory() {
	//		return category;
	//	}

	/**
	 * @param menu the menu to set
	 */
	public void setMenu(MenuItem menu) {
		this.menu = menu;
	}

	/**
	 * 
	 * @return the menu
	 */
	public MenuItem getMenu() throws DataAccessException {

		return menu;
	}

	/**
	 * @param parentMenu the parentMenu to set
	 */
	public void setParentMenu(MenuItem parentMenu) {
		this.parentMenu = parentMenu;
	}

	/**
	 * 根据传过来的parentMenuId来初始化menu属性，如果存在有效parentMenuId，则从persistence context中获取parentMenu对象；
	 * 否则返回null
	 * @return the parentMenu
	 */
	public MenuItem getParentMenu()  throws DataAccessException {
		if (parentMenuId > 0) {
			parentMenu = menuItemMgr.find(parentMenuId);
		}
		return parentMenu;
	}


	@Action(value = "/menuTreeData",results = @Result(type = "plainText", name = "xmlMessage"))
	public String buildTreeDataXml() {
		try {
			Element root = new Element("tree").setAttribute("id", String.valueOf(0));



			Document document = new Document(root);

			for (MenuItem rootMenu : menuItemMgr.listRootMenus()) {
				root.addContent(populateTreeNode(rootMenu));
			}
			HttpServletResponse response = ServletActionContext.getResponse();
			responseXml(document,response);
			return "xmlMessage";
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		}

	}

	/**
	 * @param document
	 * @param response
	 * @throws IOException
	 */
	public void responseXml(Document document, ServletResponse response) throws IOException {
		XMLOutputter xmlOut = new XMLOutputter();
		response.setContentType("text/xml ");
		PrintWriter pw = response.getWriter();
		xmlOut.output(document, pw);
	}

	/**
	 * @return
	 * 
	 */
	@Action(value = "/updateTreeData",results = @Result(type = "plainText", name = "xmlMessage"))
	public String updateTreeData() {
		try {
			HttpServletRequest request = ServletActionContext.getRequest();
			long menuitemId = Long.valueOf(request.getParameter("tr_id"));
			String editorStatus = request.getParameter("!nativeeditor_status");
			String text = request.getParameter("tr_text");
			String pid = request.getParameter("tr_pid");
			String url = request.getParameter("url");
			if (pid != null && !pid.isEmpty()) {
				parentMenuId = Long.valueOf(pid);
			}

			Element root = new Element("data");
			Document document = new Document(root);



			switch (NativeEditorStatus.valueOf(editorStatus.toUpperCase())) {
			case DELETED:
				menu = menuItemMgr.find(menuitemId);
				menuItemMgr.remove(menu);
				root.addContent(new Element("action")
				.setAttribute("type",NativeEditorStatus.DELETED.getOperation())
				.setAttribute("sid",String.valueOf(menuitemId))
				.setAttribute("tid",String.valueOf(menuitemId)));
				break;

			case INSERTED:

				menu = new MenuItem(text,url,menuItemMgr.find(parentMenuId));
				menuItemMgr.persist(menu);
				root.addContent(new Element("action")
				.setAttribute("type",NativeEditorStatus.INSERTED.getOperation())
				.setAttribute("sid",String.valueOf(menuitemId))
				.setAttribute("tid",String.valueOf(menu.getId())));

				break;

			case UPDATED:
				menu = menuItemMgr.find(menuitemId);
				menu.setName(text);
				menu.setUrl(url);
				root.addContent(new Element("action")
				.setAttribute("type",NativeEditorStatus.UPDATED.getOperation())
				.setAttribute("sid",String.valueOf(menuitemId))
				.setAttribute("tid",String.valueOf(menuitemId)));
				//			menu.setUrl(url);
				menuItemMgr.merge(menu);
				break;

			default:
				throw new RuntimeException("Unknow action type!!");
				//				break;
			}

			responseXml(document, ServletActionContext.getResponse());
			return "xmlMessage";
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		} catch (DataAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			throw new RuntimeException("Operation failed.",e);
		}

	}

	public Element populateTreeNode(MenuItem item) throws Exception {
		Element element = new Element("item")
		.setAttribute("id", String.valueOf(item.getId()))
		.setAttribute("text",item.getName())
		.setAttribute("im0", "leaf.gif")
		.setAttribute("im1", "folderClosed.gif")
		.setAttribute("im2", "folderOpen.gif")
		.addContent(new Element("userdata").setAttribute("name", "url").setText(item.getUrl()));
		for (MenuItem subitem : item.getChildMenus()) {
			//递归组装所有子节点
			element.addContent(populateTreeNode(subitem));
		}
		return element;
	}



}

